OPC Studio User's Guide and Reference
Installed Examples - Server Windows Forms - UAServerWindowsFormsDemo
// A fully functional OPC UA demo server running in Windows Forms host.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System.Linq;
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.Forms.Application;
using OpcLabs.EasyOpc.UA.OperationModel;
using OpcLabs.EasyOpc.UA.Services;
using UAServerDemoLibrary;

namespace UAServerWindowsFormsDemo
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            // Instantiating the EasyUAServer here, and not inline where the field is declared, is important for it to
            // acquire the proper synchronization context.
            _server = new EasyUAServer();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            // Extend the form's system menu by a command for OPC UA application management.
            EasyUAFormsApplication.Instance.AddToSystemMenu(this);

            // Define various nodes.
            DataNodes.AddToParent(_server.Objects);
            DemoNodes.AddToParent(_server.Objects);

            // Hook events to the server object.
            _server.EndpointStateChanged += ServerOnEndpointStateChanged;

            // Obtain the server connection monitoring service.
            IEasyUAServerConnectionMonitoring serverConnectionMonitoring = _server.GetService<IEasyUAServerConnectionMonitoring>();
            if (!(serverConnectionMonitoring is null))
            {
                // Hook events to the connection monitoring service.
                serverConnectionMonitoring.ClientSessionConnected += ServerConnectionMonitoringOnClientSessionConnected;
                serverConnectionMonitoring.ClientSessionDisconnected += ServerConnectionMonitoringOnClientSessionDisconnected;
            }

            _server.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _server.Stop();
        }

        private void ServerOnEndpointStateChanged(object sender, EasyUAServerEndpointStateChangedEventArgs e)
        {
            // Note that since we have created the EasyUAServer on the UI thread, we can access the UI controls in its
            // event handlers directly, because the events are raised using the synchronization context acquired at time of
            // the creation.

            string endpointUrlString = e.EndpointUrlString;
            ListViewItem listViewItem = endpointStateListView.Items.Cast<ListViewItem>().FirstOrDefault(item => 
                item.Text == endpointUrlString);
            if (listViewItem is null)
            {
                listViewItem = new ListViewItem(endpointUrlString);
                endpointStateListView.Items.Add(listViewItem);
                listViewItem.SubItems.Add("");
                listViewItem.SubItems.Add("");
            }
            listViewItem.SubItems[1].Text = e.ConnectionState.ToString();
            listViewItem.SubItems[2].Text = e.Exception?.Message ?? "";
        }

        private void ServerConnectionMonitoringOnClientSessionConnected(object sender, EasyUAClientSessionConnectionEventArgs e)
        {
            // Note that since we have created the EasyUAServer on the UI thread, we can access the UI controls in its
            // event handlers directly, because the events are raised using the synchronization context acquired at time of
            // the creation.

            var listViewItem = new ListViewItem(e.SessionId.Identifier.ToString());
            listViewItem.SubItems.Add(e.SessionName);
            connectionsListView.Items.Add(listViewItem);
        }

        private void ServerConnectionMonitoringOnClientSessionDisconnected(object sender, EasyUAClientSessionConnectionEventArgs e)
        {
            // Note that since we have created the EasyUAServer on the UI thread, we can access the UI controls in its
            // event handlers directly, because the events are raised using the synchronization context acquired at time of
            // the creation.

            string identifierString = e.SessionId.Identifier.ToString();
            ListViewItem listViewItem = connectionsListView.Items.Cast<ListViewItem>().FirstOrDefault(item =>
                item.Text == identifierString);
            if (!(listViewItem is null))
                connectionsListView.Items.Remove(listViewItem);
        }

        private readonly EasyUAServer _server;
    }
}
// A fully functional OPC UA demo server running in Windows Forms host.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

namespace UAServerWindowsFormsDemo
{
    partial class MainForm
    {
        /// <summary>
        ///  Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        ///  Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///  Required method for Designer support - do not modify
        ///  the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.endpointStateListView = new System.Windows.Forms.ListView();
            this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.label2 = new System.Windows.Forms.Label();
            this.connectionsListView = new System.Windows.Forms.ListView();
            this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(13, 13);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(83, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "Endpoint states:";
            // 
            // endpointStateListView
            // 
            this.endpointStateListView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.endpointStateListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.columnHeader1,
            this.columnHeader2,
            this.columnHeader3});
            this.endpointStateListView.FullRowSelect = true;
            this.endpointStateListView.HideSelection = false;
            this.endpointStateListView.Location = new System.Drawing.Point(13, 30);
            this.endpointStateListView.Name = "endpointStateListView";
            this.endpointStateListView.Size = new System.Drawing.Size(775, 97);
            this.endpointStateListView.TabIndex = 1;
            this.endpointStateListView.UseCompatibleStateImageBehavior = false;
            this.endpointStateListView.View = System.Windows.Forms.View.Details;
            // 
            // columnHeader1
            // 
            this.columnHeader1.Text = "Endpoint URL";
            this.columnHeader1.Width = 240;
            // 
            // columnHeader2
            // 
            this.columnHeader2.Text = "State";
            this.columnHeader2.Width = 80;
            // 
            // columnHeader3
            // 
            this.columnHeader3.Text = "Message";
            this.columnHeader3.Width = 440;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(13, 134);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(69, 13);
            this.label2.TabIndex = 2;
            this.label2.Text = "Connections:";
            // 
            // connectionsListView
            // 
            this.connectionsListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.connectionsListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.columnHeader4,
            this.columnHeader5});
            this.connectionsListView.FullRowSelect = true;
            this.connectionsListView.HideSelection = false;
            this.connectionsListView.Location = new System.Drawing.Point(13, 151);
            this.connectionsListView.Name = "connectionsListView";
            this.connectionsListView.Size = new System.Drawing.Size(775, 287);
            this.connectionsListView.TabIndex = 3;
            this.connectionsListView.UseCompatibleStateImageBehavior = false;
            this.connectionsListView.View = System.Windows.Forms.View.Details;
            // 
            // columnHeader4
            // 
            this.columnHeader4.Text = "Identifier";
            this.columnHeader4.Width = 80;
            // 
            // columnHeader5
            // 
            this.columnHeader5.Text = "Session Name";
            this.columnHeader5.Width = 480;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.connectionsListView);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.endpointStateListView);
            this.Controls.Add(this.label1);
            this.Name = "MainForm";
            this.Text = "OPC Wizard Server Windows Forms Demo";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }
// A fully functional OPC UA demo server running in Windows Forms host.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using System.Windows.Forms;
using OpcLabs.EasyOpc.UA;

namespace UAServerWindowsFormsDemo
{
    internal static class Program
    {
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
#if (NET6_0_OR_GREATER)
            // To customize application configuration such as set high DPI settings or default font,
            // see https://aka.ms/applicationconfiguration.
            ApplicationConfiguration.Initialize();
#endif

            // Enable the Windows Forms interaction by the server.
            EasyUAServer.SharedParameters.PluginSetups.FindName("UAWindowsFormsInteraction").Enabled = true;

            Application.Run(new MainForm());
        }
    }
}
See Also

Installed Examples - Server Console

Installed Examples - Server Library

Installed Examples - Server Windows Service

Installed Examples - Server Worker Service

Examples - Server OPC Unified Architecture